﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Corecalc;

namespace Sisal
{
    class MultiProcessorModel
    {
        public static double TSched = 10.0;   //100 cycles
        public static double TMin = 0.0;

        public static readonly Func<double, int> bytesToCycles = cs => (int)Math.Ceiling(cs * 0.125);
        public static readonly Func<int, double> cyclesToBytes = bs => (1.0 / 0.125) * bs;

        //Multiprocessor model
        public static double cyclesToReadOneByte = 5.0;
        public static double cyclesToWriteOneByte = 5.0;
        public static int ProcessorCount = 8;

        public static readonly Func<int, double> Rc = bytes => cyclesToReadOneByte * bytes;    //Read communication overhead (bytes -> cycles)
        public static readonly Func<int, double> Wc = bytes => cyclesToWriteOneByte * bytes;   //Write communication overhead (bytes -> cycles)

        private static Dictionary<string, int> communicationCosts = new Dictionary<string, int> {
            { "int", 4 },
            { "double", 8 },
            { "bool", 1 },
            { "char", 2 }
        };

        private static Dictionary<string, double> simpleExecutionTimeCosts = new Dictionary<string, double> {
            { "+", 1.0 },
            { "-", 1.0 },
            { "/", 1.5 },         //Division may be 22 times larger than add, sub, ...
            { "*", 1.0 },
            { ">", 1.0 },
            { "<", 1.0 },
            { ">=", 1.0 },
            { "<=", 1.0 },
            { "&", 1.0 },
            { "<>", 1.0 },
            { "=", 1.0 },
            { "IF", 1.0 },
            { "COS", 5 },
            { "SIN", 5 },
            { "SQRT", 5 },
            { "Const", 0.5 },
            { "Error", 0.0 },
            { "CellRef", 0.0 },
            { "CellArea", 0.0 }
        };

        public static int FromTextValue(string value) {
            return communicationCosts["char"] * value.Length;
        }

        public static double GetExecutionTime(string op) {
            return simpleExecutionTimeCosts[op];
        }

        public static int GetCommunicationCost(string type) {
            return communicationCosts[type];
        }

        public static int GetCommunicationCost(FullCellAddr fca) {
            Cell cell = fca.sheet[fca.ca];

            if (cell is NumberCell) {
                return GetCommunicationCost("double");
            } else if (cell is TextCell) {
                TextCell txtCell = cell as TextCell;
                return txtCell.value.CommunicationCost;
            } else if (cell is BlankCell) {
                return 0;
            } else {
                //throw new System.NotImplementedException();
                Formula formula = cell as Formula;
                return formula.CommunicationCost;
            }
        }
    }

    //class Nodes
    //{
    //    private static Dictionary<FullCellAddr, SisalNode> nodes = new Dictionary<FullCellAddr, SisalNode>();

    //    public static bool ContainsKey(FullCellAddr fca) {
    //        return nodes.ContainsKey(fca);
    //    }

    //    public static void Add(FullCellAddr fca, SisalNode node) {
    //        nodes.Add(fca, node);
    //    }

    //    public static SisalNode Get(FullCellAddr node) {
    //        return nodes[node];
    //    }

    //    public static void PrintDictionary() {
    //        Console.WriteLine("- - - - - - - - - - - Dictionary - - - - - - - - - - - - -");

    //        foreach (var key in nodes.Keys) {
    //            Console.WriteLine("{0}: {1}", key, nodes[key]);
    //        }
    //    }

    //    public static void ClearDictionary() {
    //        nodes.Clear();
    //    }
    //}
}
